using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using Xeml.Document;
using Xeml.Document.Contracts;
using Mpi.Common.Collections;
using System.Threading;

namespace Xid.Controls
{
    public partial class SamplingStrategyCtrl : UserControl
    {
        public bool IsValidTemplate
        {
            get
            {
                if (germPlasmCtrls.Count == 0)
                    return false;
                foreach (var item in germPlasmCtrls)
                {
                    if (item.ObservationControls.Count == 0)
                        return false;
                    foreach (var obc in item.ObservationControls)
                    {
                        if (obc.ObservationPrototype.Partitions.Count == 0)
                            return false;
                        foreach (var part in obc.ObservationPrototype.Partitions)
                        {
                            if (part.Material.Count == 0)
                                return false;
                        }
                    }
                }
                return true;
            }
        }
        public SamplingStrategyCtrl()
        {
            InitializeComponent();
            tableLayoutPanel1.RowCount = 0;
        }

        private List<SsC_GermPlasmCtrl> germPlasmCtrls = new List<SsC_GermPlasmCtrl>();

        #region Layout methods


        private void kryptonButtonAddGp_Click(object sender, EventArgs e)
        {

            if (kryptonDataGridView1.SelectedCells.Count > 0)
            {
                tableLayoutPanel1.SuspendLayout();
                SsC_GermPlasmCtrl sscGermPlasm = new SsC_GermPlasmCtrl();
                sscGermPlasm.ObservationCtrlAdded += new EventHandler<ObservationControlEventArgs>(sscGermPlasm_ObservationCtrlAdded);
                sscGermPlasm.ObservationCtrlRemoved += new EventHandler<ObservationControlEventArgs>(sscGermPlasm_ObservationCtrlRemoved);
                //sscGermPlasm.ObservationAdded += new EventHandler<Mpi.Common.Collections.ItemEventArgs<Xeml.Document.Observation>>(sscGermPlasm_ObservationAdded);
                //sscGermPlasm.ObservationRemoved += new EventHandler<Mpi.Common.Collections.ItemEventArgs<Xeml.Document.Observation>>(sscGermPlasm_ObservationRemoved);


                germPlasmCtrls.Add(sscGermPlasm);

                foreach (DataGridViewCell item in kryptonDataGridView1.SelectedCells)
                {
                    StringWrapper swtoaddd = _pools.Find(delegate(StringWrapper sw) { return sw.Value == (string)item.Value; });
                    sscGermPlasm.AddPool(swtoaddd);
                }

                //foreach (ListViewItem lvi in listViewGermPlasm.SelectedItems)
                //{
                //    sscGermPlasm.AddPool(lvi.Tag as StringWrapper);
                //}

                //sscGermPlasm.IndividualsPool = (IndividualsPool)e.Item.Tag;
                sscGermPlasm.Anchor = AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top | AnchorStyles.Bottom;
                tableLayoutPanel1.RowCount++;

                tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Percent, 1));
                tableLayoutPanel1.Controls.Add(sscGermPlasm, 0, tableLayoutPanel1.RowCount - 1);

                NormalizeRowHeight();

                tableLayoutPanel1.ResumeLayout(true);
            }
        }

        void sscGermPlasm_ObservationCtrlRemoved(object sender, ObservationControlEventArgs e)
        {
            SsC_GermPlasmCtrl ssc_gp = sender as SsC_GermPlasmCtrl;
            int rowindxGp = tableLayoutPanel1.GetRow(ssc_gp);
            int rowSpanGp = tableLayoutPanel1.GetRowSpan(ssc_gp);

            SsC_ObservationControl ssc_oc = e.Control;
            int rowindxOc = tableLayoutPanel1.GetRow(ssc_oc);
            int rowSpanOc = tableLayoutPanel1.GetRowSpan(ssc_oc);

            tableLayoutPanel1.SuspendLayout();
            RemovAllControlsFromRows(rowindxOc, rowindxOc + (rowSpanOc - 1), 1);

            tableLayoutPanel1.SetRowSpan(ssc_gp, Math.Max(rowSpanGp - rowSpanOc, 1));


            int rowsToRem = CalcRowsToRemove(rowindxGp, rowindxOc, rowSpanOc);
            MoveAllUp(rowindxOc + rowSpanOc, rowsToRem);


            tableLayoutPanel1.RowCount = tableLayoutPanel1.RowCount - rowsToRem;


            tableLayoutPanel1.ResumeLayout(true);

        }

        void sscGermPlasm_ObservationCtrlAdded(object sender, ObservationControlEventArgs e)
        {
            SsC_GermPlasmCtrl ssc = sender as SsC_GermPlasmCtrl;

            tableLayoutPanel1.SuspendLayout();
            int rowIndx = tableLayoutPanel1.GetRow(ssc);
            int rowSpan = tableLayoutPanel1.GetRowSpan(ssc);
            int neededRowInc = 0;
            if (ssc.ObservationControls.Count > 1)
                neededRowInc = 1;


            if (neededRowInc > 0)
            {
                tableLayoutPanel1.RowCount = tableLayoutPanel1.RowCount + neededRowInc;
                tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Percent, 1));
                MoveAllDown(rowIndx + (rowSpan - 1) + neededRowInc);
                tableLayoutPanel1.SetRowSpan(ssc, rowSpan + neededRowInc);
            }
            SsC_ObservationControl obCtrl = e.Control;
            obCtrl.Populate(_xemlDoc);
            obCtrl.Anchor = AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top | AnchorStyles.Bottom;
            tableLayoutPanel1.Controls.Add(obCtrl, 1, rowIndx + (rowSpan - 1) + neededRowInc);



            NormalizeRowHeight();
            tableLayoutPanel1.ResumeLayout(true);


            obCtrl.PartitionCtrlAdded += new EventHandler<SsC_ObservationControl.PartitionControlEventArgs>(obCtrl_PartitionCtrlAdded);
            obCtrl.PartitionCtrlRemoved += new EventHandler<SsC_ObservationControl.PartitionControlEventArgs>(obCtrl_PartitionCtrlRemoved);

        }

        void obCtrl_PartitionCtrlRemoved(object sender, SsC_ObservationControl.PartitionControlEventArgs e)
        {
            SsC_ObservationControl ssc_ObCtrl = sender as SsC_ObservationControl;
            int rowIndxOc = tableLayoutPanel1.GetRow(ssc_ObCtrl);
            int rowSpanOc = tableLayoutPanel1.GetRowSpan(ssc_ObCtrl);

            SsC_PartitionCtrl ssc_ParCtrl = e.Control;
            int rowIndxPc = tableLayoutPanel1.GetRow(ssc_ParCtrl);
            int rowSpanPc = tableLayoutPanel1.GetRowSpan(ssc_ParCtrl);

            int rowsToRem = CalcRowsToRemove(rowIndxOc, rowIndxPc, rowSpanPc);

            tableLayoutPanel1.SuspendLayout();
            RemovAllControlsFromRows(rowIndxPc, rowIndxPc + rowsToRem, 2);
            tableLayoutPanel1.SetRowSpan(ssc_ObCtrl, rowSpanOc - rowsToRem);
            tableLayoutPanel1.SetRowSpan(ssc_ObCtrl.CreatorCtrl, tableLayoutPanel1.GetRowSpan(ssc_ObCtrl.CreatorCtrl) - rowsToRem);
            MoveAllUp(rowIndxPc + rowSpanPc, rowsToRem);

            tableLayoutPanel1.RowCount = tableLayoutPanel1.RowCount - rowsToRem;

            if (ssc_ObCtrl.PartitionCtrls.Count == 0)
                ssc_ObCtrl.SampleCtrl = null;

            tableLayoutPanel1.ResumeLayout(true);


        }

        void obCtrl_PartitionCtrlAdded(object sender, SsC_ObservationControl.PartitionControlEventArgs e)
        {

            while (_ontologyLoader.IsBusy)
            {
                Thread.Sleep(1000);
                Application.DoEvents();
            }


            SsC_ObservationControl ssc_ObCtrl = sender as SsC_ObservationControl;



            int rowIndx = tableLayoutPanel1.GetRow(ssc_ObCtrl);
            int rowSpan = tableLayoutPanel1.GetRowSpan(ssc_ObCtrl);
            int neededRowInc = 0;
            if (ssc_ObCtrl.PartitionCtrls.Count > 1)
                neededRowInc = 1;

            if (neededRowInc > 0)
            {
                tableLayoutPanel1.RowCount = tableLayoutPanel1.RowCount + neededRowInc;
                tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Percent, 1));
                MoveAllDown(rowIndx + (rowSpan - 1) + neededRowInc);

                tableLayoutPanel1.SetRowSpan(ssc_ObCtrl, rowSpan + neededRowInc);
                tableLayoutPanel1.SetRowSpan(ssc_ObCtrl.CreatorCtrl, tableLayoutPanel1.GetRowSpan(ssc_ObCtrl.CreatorCtrl) + neededRowInc);
            }

            SsC_PartitionCtrl ssc_partCtrl = e.Control;
            ssc_partCtrl.Populate(_xemlDoc);
            ssc_partCtrl.CreatorCtrl = ssc_ObCtrl;
            ssc_partCtrl.Anchor = AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top | AnchorStyles.Bottom;

            ////jahu
            //ssc_partCtrl.AutoScroll = true;
            //ssc_partCtrl.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
            ////ssc_partCtrl.AutoScrollMinSize = new Size(50;
            //tableLayoutPanel1.Padding = new Padding(0, 0, 0, SystemInformation.HorizontalScrollBarHeight);


            tableLayoutPanel1.Controls.Add(ssc_partCtrl, 2, rowIndx + (rowSpan - 1) + neededRowInc);


            if (ssc_ObCtrl.PartitionCtrls.Count == 1)
            {
                ssc_ObCtrl.SampleCtrl = new SsC_SampleCtrl();
                ssc_ObCtrl.SampleCtrl.Anchor = AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top | AnchorStyles.Bottom;
                tableLayoutPanel1.Controls.Add(ssc_ObCtrl.SampleCtrl, 3, rowIndx);
                tableLayoutPanel1.SetRowSpan(ssc_ObCtrl.SampleCtrl, rowSpan + neededRowInc);
            }
            else if (ssc_ObCtrl.PartitionCtrls.Count > 1)
            {
                tableLayoutPanel1.SetRowSpan(ssc_ObCtrl.SampleCtrl, rowSpan + neededRowInc);
            }

            //ssc_partCtrl.SampleCtrlAdded += new EventHandler<SampleControlEventArgs>(ssc_partCtrl_SampleCtrlAdded);

            //ssc_partCtrl.AddSampleCtrl();
            NormalizeRowHeight();
            tableLayoutPanel1.ResumeLayout(true);

        }


        #endregion

        #region Helper methods

        private int CalcRowsToRemove(int parentIndx, int myIndx, int mySpawn)
        {
            if (myIndx == parentIndx)
                return mySpawn - 1;
            else
                return mySpawn;
        }

        private void RemovAllControlsFromRows(int start, int end, int startCol)
        {
            List<Control> toRem = new List<Control>();
            foreach (Control c in this.tableLayoutPanel1.Controls)
            {
                if (tableLayoutPanel1.GetRow(c) >= start && tableLayoutPanel1.GetRow(c) <= end && tableLayoutPanel1.GetColumn(c) >= startCol)
                    toRem.Add(c);

                int x = tableLayoutPanel1.GetRow(c);
            }
            foreach (Control c in toRem)
            {
                tableLayoutPanel1.Controls.Remove(c);
            }
        }


        private void NormalizeRowHeight()
        {
            if (tableLayoutPanel1.RowCount > 0)
            {
                foreach (RowStyle rs in tableLayoutPanel1.RowStyles)
                {
                    rs.Height = 100 / tableLayoutPanel1.RowCount;

                    //jahu
                    rs.SizeType = SizeType.AutoSize;
                }
            }
        }


        private void MoveAllDown(int startIndx)
        {
            foreach (Control c in tableLayoutPanel1.Controls)
            {
                int i = tableLayoutPanel1.GetRow(c);
                if (i >= startIndx)
                    tableLayoutPanel1.SetRow(c, i + 1);
            }
        }

        private void MoveAllUp(int startIndx, int moves)
        {
            foreach (Control c in tableLayoutPanel1.Controls)
            {
                int i = tableLayoutPanel1.GetRow(c);
                if (i >= startIndx)
                    tableLayoutPanel1.SetRow(c, i - moves);
            }
        }
        #endregion


        public List<SampleTemplate> CalculateTemplates()
        {
            List<SampleTemplate> ret = new List<SampleTemplate>();
            foreach (SsC_GermPlasmCtrl gpCtrl in this.germPlasmCtrls)
            {
                foreach (SsC_ObservationControl obCtrl in gpCtrl.ObservationControls)
                {

                    if (obCtrl.PartitionCtrls.Count > 0)
                    {
                        foreach (Xid.Controls.StringWrapper ip in gpCtrl.IndividualPools)
                        {
                            SampleTemplate st = new SampleTemplate();
                            st.Observation = new Observation(obCtrl.ObservationPrototype);
                            st.IndividualsPool = ip.Value;
                            st.ObservationCount = obCtrl.PoolSize;
                            st.ReplicaCount = obCtrl.SampleCtrl.ReplicaCount;
                            //foreach (SsC_PartitionCtrl pCtrl in obCtrl.PartitionCtrls)
                            //{
                            //    st.ReplicaPerPartition.Add(pCtrl.Partition, pCtrl.SampleCtrls[0].ReplicaCount);
                            //}
                            ret.Add(st);
                        }

                    }

                }
            }
            return ret;
        }

        private IDocument _xemlDoc;
        private List<StringWrapper> _pools;


        BackgroundWorker _ontologyLoader;
        public void PopulateIndividualPools(IDocument xemlDoc)
        {
            _xemlDoc = xemlDoc;

            _ontologyLoader = new BackgroundWorker();
            _ontologyLoader.DoWork += new DoWorkEventHandler(_ontologyLoader_DoWork);
            _ontologyLoader.RunWorkerAsync();

            _pools = new List<StringWrapper>();
            foreach (TreeNode<StoryBase> stNode in xemlDoc.StoryBoard.VirtualRoot.SubNodes(false))
            {
                foreach (IndividualsPool ip in (stNode.Content as Story).Pools)
                {
                    if (!_pools.Exists(delegate(StringWrapper sw) { return sw.Value == ip.GermPlasm; }))
                        _pools.Add(new StringWrapper(ip.GermPlasm));
                }
            }

            stringWrapperBindingSource.DataSource = _pools;
            stringWrapperBindingSource.ResetBindings(false);

            //this.listViewGermPlasm.Items.Clear();
            //foreach (StringWrapper ip in pools)
            //{
            //    ListViewItem lvi = new ListViewItem();
            //    lvi.Text = ip.Value;
            //    lvi.Tag = ip;
            //    listViewGermPlasm.Items.Add(lvi);
            //}
            // this.listViewGermPlasm.ItemChecked +=new ItemCheckedEventHandler(listViewGermPlasm_ItemChecked);
        }

        void _ontologyLoader_DoWork(object sender, DoWorkEventArgs e)
        {
            if (_xemlDoc != null)
            {
                foreach (var item in _xemlDoc.DocumentResources.OrganismStructureOntologyHandler)
                {
                    item.LoadOntology();
                }
            }

        }

        //private void listViewGermPlasm_SizeChanged(object sender, EventArgs e)
        //{
        //    listViewGermPlasm.Columns[0].Width = listViewGermPlasm.Width-2;
        //}

        private void kryptonButtonRemoveGp_Click(object sender, EventArgs e)
        {

            if (this.germPlasmCtrls.Count > 0)
            {
                int startrow = tableLayoutPanel1.GetRow(germPlasmCtrls[germPlasmCtrls.Count - 1]);
                int rowcount = tableLayoutPanel1.GetRowSpan(germPlasmCtrls[germPlasmCtrls.Count - 1]);
                this.RemovAllControlsFromRows(startrow, startrow + (rowcount - 1), 0);
                this.tableLayoutPanel1.RowCount = this.tableLayoutPanel1.RowCount - rowcount;
                this.germPlasmCtrls.RemoveAt(germPlasmCtrls.Count - 1);
            }

        }
    }

    public class SampleTemplate
    {
        //private Dictionary<Partition,int> replPerPartition = new Dictionary<Partition,int>();

        //public Dictionary<Partition,int> ReplicaPerPartition
        //{
        //    get { return replPerPartition; }
        //    set { replPerPartition = value; }
        //}

        private string germPlasm;
        private int observationCount;
        //private TimeSpan observationDuration;
        //private List<string> material;
        private int replCount;
        //private bool destrObservation;

        private Observation ob;

        public Observation Observation
        {
            get { return ob; }
            set { ob = value; }
        }


        //public bool DestructiveObservation
        //{
        //    get { return destrObservation; }
        //    set { destrObservation = value; }
        //}


        public int ReplicaCount
        {
            get { return replCount; }
            set { replCount = value; }
        }


        //public List<string> Material
        //{
        //    get { return material; }
        //    set { material = value; }
        //}


        //public TimeSpan ObservationDuration
        //{
        //    get { return observationDuration; }
        //    set { observationDuration = value; }
        //}


        public int ObservationCount
        {
            get { return observationCount; }
            set { observationCount = value; }
        }


        public string IndividualsPool
        {
            get { return germPlasm; }
            set { germPlasm = value; }
        }

    }

    public class StringWrapper : IComparable
    {
        private string _text;

        public string Value
        {
            get { return _text; }
            set { _text = value; }
        }


        public StringWrapper(string s)
        {
            _text = s;
        }


        #region IComparable Members

        public int CompareTo(object obj)
        {
            if (_text != null)
                return _text.CompareTo(obj);
            else
                return -1;
        }

        #endregion
    }
}
